<template>
  <transition name="fade-scale">
    <div class="setting-container" v-dialog-drag v-if="visible">
      <div class="dialog-title">
        <div class="title drag-title">{{ $t("系统设置") }}</div>
        <span class="dialog-active">
          <i
            class="el-icon-minus dialog-icon-screen"
            @click.stop="onMinimize"
          />
          <i
            v-show="!minimize"
            class="el-icon-copy-document dialog-icon-screen"
            @click.stop="onScreen"
          />
          <i class="el-icon-close dialog-icon-close" @click.stop="onClose" />
        </span>
      </div>
      <div class="dialog-content" v-show="!minimize">
        <setting-content :settings="settings" />
      </div>
    </div>
  </transition>
</template>

<script>
import SettingContent from "@/components/setting-content";
export default {
  name: "setting-dialog",
  components: {
    SettingContent,
  },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  directives: {
    "dialog-drag": {
      bind(el) {
        const dialogHeaderEl = el.querySelector(".drag-title");
        // 获取原有属性 el.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
        const sty = el.currentStyle || window.getComputedStyle(el, null);
        dialogHeaderEl.style.cursor = "move";
        const dragParentNode = document.getElementById("page-container");
        const dragParentNodeClientRect = dragParentNode.getBoundingClientRect();

        dialogHeaderEl.onmousedown = (e) => {
          // 鼠标按下，计算当前元素距离可视区的距离
          const disX = e.clientX - dialogHeaderEl.offsetLeft;
          const disY = e.clientY - dialogHeaderEl.offsetTop;

          // 获取开始移动时的位置信息, 单位px 正则匹配替换
          let styL, styT;
          // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
          if (sty.left.includes("%")) {
            styL =
              +document.body.clientWidth * (+sty.left.replace(/%/g, "") / 100);
            styT =
              +document.body.clientHeight * (+sty.top.replace(/%/g, "") / 100);
          } else {
            styL = +sty.left.replace(/px/g, "");
            styT = +sty.top.replace(/px/g, "");
          }
          document.onmousemove = function (e) {
            // 通过事件委托，计算移动的距离
            const l = e.clientX - disX;
            const t = e.clientY - disY;
            // 移动坐标
            let moveLeft = l + styL;
            let moveTop = t + styT;

            // 定义最小值
            let minX = dragParentNodeClientRect.left;
            let minY = dragParentNodeClientRect.top;

            // 定义最大值
            let maxX =
              dragParentNode.offsetWidth -
              el.offsetWidth +
              dragParentNodeClientRect.left;
            let maxY =
              dragParentNode.offsetHeight -
              el.offsetHeight +
              dragParentNodeClientRect.top;

            // 判断是否移出屏幕外
            let left =
              moveLeft <= minX ? minX : moveLeft >= maxX ? maxX : moveLeft;
            let top = moveTop <= minY ? minY : moveTop >= maxY ? maxY : moveTop;

            // 移动当前元素
            el.style.left = `${left}px`;
            el.style.top = `${top}px`;
          };

          document.onmouseup = function (e) {
            document.onmousemove = null;
            document.onmouseup = null;
          };
        };
      },
      inserted(el) {
        let dragParentNode = document.getElementById("page-container");
        let dragParentNodeClientRect = dragParentNode.getBoundingClientRect();
        // 设置弹窗剧中
        const left = (dragParentNode.offsetWidth - el.offsetWidth) / 2;
        const top = (dragParentNode.offsetHeight - el.offsetHeight) / 2;
        el.style.left = `${dragParentNodeClientRect.left + left}px`;
        el.style.top = `${dragParentNodeClientRect.top + top}px`;
        // 监听窗口大小变化
        window.onresize = () => {
          const left = (dragParentNode.offsetWidth - el.offsetWidth) / 2;
          const top = (dragParentNode.offsetHeight - el.offsetHeight) / 2;
          el.style.left = `${dragParentNodeClientRect.left + left}px`;
          el.style.top = `${dragParentNodeClientRect.top + top}px`;
        };
      },
      unbind(el) {
        clearInterval(el.__vueSetInterval__);
        // 销毁监听窗口大小变化
        window.onresize = null;
      },
    },
  },
  data() {
    return {
      settings: {
        theme: true,
        language: false,
        hotkey: true,
        other: true,
      },
      screen: false, // 全屏
      // 最小化
      minimize: false,
      // 旧窗口信息
      originalScreen: {
        width: 0,
        height: 0,
        left: 0,
        top: 0,
      },
      // 最小化前窗口信息
      minilScreen: {
        width: 0,
        height: 0,
        left: 0,
        top: 0,
      },
    };
  },
  methods: {
    // 关闭设置弹窗
    onClose() {
      this.$emit("update:visible", false);
    },
    async onScreen() {
      if (this.minimize) return;
      this.screen = !this.screen;
      if (this.screen) {
        await this.originalSize();
        // 设置弹窗剧中
        await this.setDialogSize();

        // 监听窗口大小变化
        window.onresize = () => {
          this.setDialogSize();
        };
      } else {
        this.restore();
        // 销毁监听窗口大小变化
        window.onresize = null;
      }
    },
    async onMinimize() {
      this.minimize = !this.minimize;
      if (this.minimize) {
        this.minilScreen = {
          width: this.$el.offsetWidth,
          height: this.$el.offsetHeight,
          left: this.$el.offsetLeft,
          top: this.$el.offsetTop,
        };
        this.$el.style.width = "200px";
        this.$el.style.height = "auto";
      } else {
        this.$el.style.left = `${this.minilScreen.left}px`;
        this.$el.style.top = `${this.minilScreen.top}px`;
        this.$el.style.width = `${this.minilScreen.width}px`;
        this.$el.style.height = `${this.minilScreen.height}px`;
      }
    },
    async originalSize() {
      this.originalScreen = {
        width: this.$el.offsetWidth,
        height: this.$el.offsetHeight,
        left: this.$el.offsetLeft,
        top: this.$el.offsetTop,
      };
    },
    // 设置弹窗位置、窗口大小
    async setDialogSize() {
      let dragParentNode = document.getElementById("page-container");
      let dragParentNodeClientRect = dragParentNode.getBoundingClientRect();
      this.$el.style.left = `${dragParentNodeClientRect.left}px`;
      this.$el.style.top = `${dragParentNodeClientRect.top}px`;
      this.$el.style.width = `${dragParentNode.offsetWidth}px`;
      this.$el.style.height = `${dragParentNode.offsetHeight}px`;
    },
    // 还原窗口大小
    async restore() {
      this.$el.style.left = `${this.originalScreen.left}px`;
      this.$el.style.top = `${this.originalScreen.top}px`;
      this.$el.style.width = `${this.originalScreen.width}px`;
      this.$el.style.height = `${this.originalScreen.height}px`;
    },
  },
};
</script>

<style lang="scss" scoped>
.minimize-dialog {
  width: 200px !important;
}

.setting-container {
  position: fixed;
  top: 0px;
  left: 0px;
  z-index: 1024;
  transition: none;
  width: 646px;
  border-radius: 4px;
  padding: 0px 8px;
  background: var(--body-background);
  border: 1px solid var(--main-border);
  // box-shadow: 0 2px 12px 0 var(--main-shadow);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  overflow: hidden;

  .dialog-title {
    width: 100%;
    height: 32px;
    color: var(--main-color);
    display: flex;
    justify-content: space-between;
    align-items: center;

    & .title {
      flex: 1;
      height: 32px;
      line-height: 32px;
      overflow: hidden;
    }

    .dialog-active {
      width: 100px;
      cursor: pointer;
      display: flex;
      justify-content: flex-end;
      align-items: center;

      & i:hover {
        color: var(--main-hover);
      }
    }
  }

  .dialog-content {
    border-top: 1px solid var(--main-border);
    width: 100%;
    height: 400px;
  }

  .dialog-icon-screen {
    font-size: 16px;
    font-weight: 400;
    margin: 0 6px;
  }

  .dialog-icon-close {
    margin: 0 6px;
    font-size: 20px;
    font-weight: 400;
  }
}
</style>